// threadPool.c
#include "threadPool.h"
#include "transFile.h"
#include <stdio.h>
#define _LISTEN_QUEUE_SIZE 16

void work(const int netfd)
{
    // 传输文件
    printf("working...\n");
    transFile(netfd, "1.txt");
}

void *_threadFunc(void *threadPool)
{
    printf("_threadFunc1\n");
    if (threadPool == NULL)
    {
        printf("input parameter error.\n");
        return NULL;
    }
    threadPool_t *pool = (threadPool_t *)threadPool;
    while (1)
    {
        pthread_mutex_lock(&pool->_mutex);
        while (pool->_exitFlag == 0 && _taskQueue_is_empty(&pool->_q))
        {
            pthread_cond_wait(&pool->_cond, &pool->_mutex);
            printf("flag = %d\n", pool->_exitFlag);
        }
        // exit
        if (pool->_exitFlag == 1)
        {
            printf("recv quit from parent proccess, worker exit.\n");
            pthread_mutex_unlock(&pool->_mutex);
            pthread_exit(NULL);
        }
        task_t *newTask = _taskQueue_front(&pool->_q);
        _taskQueue_deque(&pool->_q);
        printf("worker: netfd = %d, tid = %lu\n", newTask->_clientFd,
               pthread_self());
        pthread_mutex_unlock(&pool->_mutex);
        printf("_threadFunc2\n");
        // work(netfd);

        if (newTask)
        {
            doTask(newTask);
            close(newTask->_clientFd);
            free(newTask);
        }
    }
    return NULL;
}

void threadPool_init(threadPool_t *pool, int workerNum)
{
    pthread_mutex_init(&pool->_mutex, NULL);
    pthread_cond_init(&pool->_cond, NULL);
    pool->_exitFlag = 0;
    int res = 0;

    _tidArr_init(&pool->_tidArr, workerNum);
    printf("threadPool_init\n");
    for (int i = 0; i < pool->_tidArr._worker_num; ++i)
    {
        res = pthread_create(&pool->_tidArr._arr[i], NULL, _threadFunc,
                             pool); // 直接传pool
        THREAD_ERROR_CHECK(res, "pthread_create");
    }

    _taskQueue_init(&pool->_q);
    // printf("threadPool_init success.\n");// test only
}

int tcp_init(const char *ip, const char *port)
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(sockfd, -1, "socket");
    int flag = 1;
    int res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));

    ERROR_CHECK(res, -1, "setsockopt");
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(atoi(port));
    res = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
    ERROR_CHECK(res, -1, "bind");

    res = listen(sockfd, _LISTEN_QUEUE_SIZE);
    ERROR_CHECK(res, -1, "listen");

    // printf("tcp_init success.\n");// test only

    return sockfd;
}

int epollAdd(int epfd, int fd)
{
    struct epoll_event ev;
    ev.data.fd = fd;
    ev.events = EPOLLIN;
    int epoll_ctl_res = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
    ERROR_CHECK(epoll_ctl_res, -1, "epoll add error");
    return 0;
}

int epollDel(int epfd, int fd)
{
    int epoll_ctl_res = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
    ERROR_CHECK(epoll_ctl_res, -1, "epoll delete error");
    return 0;
}

/* int main() */
/* { */
/*     threadPool_t pool; */
/*     int workerNum = 10; */
/*     char ip[] = "192.168.238.128"; */
/*     char port[] = "12345"; */
/*     threadPool_init(&pool, workerNum); */
/*     int sockfd = tcp_init(ip, port); */
/*     if (sockfd < 0) { */
/*         fprintf(stderr, "tcp_init failed\n"); */
/*         return -1; */
/*     } */
/*     return 0; */
/* } */
